package com.happy3w.file.server.controller;

import com.happy3w.file.server.entity.FileEntity;
import com.happy3w.file.server.service.FileService;
import com.happy3w.toolkits.message.MessageRecorderException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.ResponseEntity;
import org.springframework.http.codec.multipart.FilePart;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;

import java.io.IOException;
import java.io.File;

@RestController
@RequestMapping("/file")
@Slf4j
public class FileController {

    private final FileService fileService;

    public FileController(FileService fileService) {
        this.fileService = fileService;
    }

    @GetMapping("/{subDir}/{uuid}")
    public Mono<ResponseEntity<Resource>> fileDownload(@PathVariable(name = "subDir") String subDir,
                                                 @PathVariable(name = "uuid") String uuid) {
        return Mono.fromCallable(() -> {
            FileEntity fileEntity = fileService.findFile(uuid);
            if (fileEntity == null) {
                throw new MessageRecorderException("资源不存在:" + uuid);
            }
            String filePath = fileService.toRealPath(subDir, fileEntity);
            Resource resource = new UrlResource(new File(filePath).toURI());
            if (!resource.isFile()) {
                throw new MessageRecorderException("资源不存在:" + uuid);
            }
            return ResponseEntity.ok(resource);
        }).onErrorResume(this::handleException)
            .subscribeOn(Schedulers.boundedElastic());
    }

    @PostMapping("/{subDir}")
    public Mono<ResponseEntity<FileEntity>> uploadFile(@RequestPart ("file") FilePart file, @PathVariable(name = "subDir") String subDir) throws IOException {
        return fileService.uploadFile(file, subDir)
                .map(ResponseEntity::ok) // 成功时返回 200 OK
                .onErrorResume(this::handleException)
                .subscribeOn(Schedulers.boundedElastic()); // 在单独的线程池中执行阻塞操作
    }

    private <T> Mono handleException(Throwable e) {
        return Mono.just(ResponseEntity.badRequest().body(e.getMessage()));
    }
}
